<?php

class HangmanController extends Controller
{
    private function errorAndEnd($action, $error) {
            $this->render($action, array('error' => $error));
            Yii::app()->end();
            }
	public function actionCreate() {
                    $error = '';
                    $request = Yii::app()->request;
                    //$jsonUrl = $request->hostInfo . $request->baseUrl . '/index.php/book/titlelist';
                    $jsonUrl = $request->hostInfo . $request->baseUrl . '/index.php/act/titlelist';
                    $ch = curl_init($jsonUrl);
                    $options = array(
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_HTTPHEADER => array
                    ('Content-type: application/json')
            );
                    curl_setopt_array( $ch, $options); 
                    $titles = json_decode(curl_exec($ch));
                    curl_close($ch);
                    if ((!is_array($titles)) || (count($titles) == 0)) {
                    $this->errorAndEnd('create', 'No titles found 
                    fetching from URL: ' . $jsonUrl);
                    }
                    for ($count = 0; $count < count($titles); $count++) {
                    if (strlen($titles[$count]) < 8) {
                    unset($titles[$count]);
                    }
                    }
                    if (count($titles) < 1) {
                    $this->errorAndEnd('create', 'No suitable titles 
                    found in database.');
                    }
                    $titles = array_merge($titles); //Renumber the array
                    $this->render('create', array('titles' => $titles));
                    
                        $hangman = new Hangman;
                        $randCount = 0;
                        $hangman->title = strtoupper($titles[mt_rand(0, count($titles) - 1)]);
                        do {
                        if ($randCount > 5) { //Even one duplicate is *highly* unlikey (1 in 2^128 if mt_rand were truly random)
                        $this->errorAndEnd('create', 'Token generation appears to be broken.');
                        }
                        $hangman->token = $this->hangmanToken();
                        $randCount++;
                        } while ((Hangman::model()->find('token=:token', 
                        array(':token'=>$hangman->token))) != null);
                        $hangman->save();
                        $this->redirect($request->hostInfo.$request->baseUrl.'/index.php/hangman/play?token=' . $hangman->token);
        }
        
	public function actionPlay()
	{
                    $message = '';
                    if (!isset($_GET['token'])) {
                            $this->errorAndEnd('play', 'No token set.');
                        }
                    $token = $_GET['token'];
                    $hangman = Hangman::model()->find('token=:token', 
                    array(':token'=>$token));
                    
                    $hangman = Hangman::model()->find('token=:token', 
                    array(':token'=>$_GET["token"]));
                    
                    
                    if ($hangman == null) {
                    $this->errorAndEnd('play', 'Invalid token.');
                    }
                    $title = strtoupper($hangman->title);
                    
                    
                    $win = false;
                    $lose = false;
                        if ($hangman->fails > 5) {
                             $lose = true;
                             }
                            else {
                                    $win = $this->assessWin($hangman->guessed, $hangman->title);
                                    if (!$win && isset($_GET['guess'])) { 
                                    $guess = strtoupper($_GET['guess']);
                                    if (strlen($guess) == 1 && ctype_alpha($guess) && 
                                    !strstr($hangman->guessed, $guess)) {
                                     if (!strstr($title, $guess)) {
                                                    $hangman->fails++;
                                                    if ($hangman->fails > 5) {
                                                            $lose = true;
                                                    }
                                                                }
                                        $hangman->guessed .= $guess;
                                        $guessed = preg_split('//', $hangman->guessed, 0, 
                                        PREG_SPLIT_NO_EMPTY);
                                        sort($guessed);
                                        $hangman->guessed = implode($guessed);
                                        $hangman->save();
                                        $win = $this->assessWin($hangman->guessed, $hangman->title);
                                    }
                                        else {
                                            $message .= 'Invalid guess. Please enter a single letter that hasnt already been guessed.';
                                                }                       
                                    }                   
                                }
                    $guessed = array();
                    foreach (preg_split('//', $hangman->guessed , 0,  PREG_SPLIT_NO_EMPTY) as $letter) 
                        {
                             $guessed[$letter] = 1;
                        }
                    $maskedTitle = '';
                    foreach (preg_split('//', $title, 0, PREG_SPLIT_NO_EMPTY) as 
                    $letter) {
                    if (!isset($guessed[$letter]) && ctype_alpha($letter)) 
                            {
                                 $maskedTitle .= '_ ';
                            }
                        else {
                                $maskedTitle .= $letter . ' ';
                            }
                    }
                     
                    $maskedTitle = preg_replace('/ /', '&nbsp;', $maskedTitle);
                    
                    
                    $this->render('play', array('maskedTitle' => $maskedTitle, 
                                    'guessed' => $hangman->guessed, 'fails' => $hangman->fails, 
                                    'win' => $win, 'lose' => $lose, 'title' => $title, 
                                    'token' => $hangman->token, 'message' => $message));

	}
        
        private function hangmanToken() {
                    $charset = '0123456789abcdef';
                    $token = '';
                    $charArr = preg_split('//', $charset , 0, 
                    PREG_SPLIT_NO_EMPTY);
                        for ($count = 0; $count < 32; $count++) {
                        $token .= $charArr[mt_rand(0, count($charArr) - 1)];
                        }
                    return $token;
                    }
                    
            private function assessWin($guesses, $title) {
                    $guessArr = array();
                            foreach (preg_split('//', strtoupper($guesses), 0, 
                            PREG_SPLIT_NO_EMPTY) as $letter) {
                            $guessArr[$letter] = true; 
                                }
                            foreach (preg_split('//', strtoupper($title), 0, 
                            PREG_SPLIT_NO_EMPTY) as $letter) {
                                        if (!isset($guessArr[$letter]) && ctype_alpha($letter)) {
                                             return false;
                                                }
                                }
                                return true;
                                if (!isset($_GET['token'])) 
                                        {
                                        $this->errorAndEnd('play', 'No token set.');
                                        }
                                        if (!$win && isset($_GET['guess'])) { 
                                            
                                $guess = strtoupper($_GET['guess']);
                                if (strlen($guess) == 1 && ctype_alpha($guess) && 
                                !strstr($hangman->guessed, $guess)) {
                                if (!strstr($title, $guess)) {
                                $hangman->fails++;
                                if ($hangman->fails > 5) {
                                $lose = true;
                                }
                                }
                                $hangman->guessed .= $guess;
                                $guessed = preg_split('//', $hangman->guessed, 0, 
                                PREG_SPLIT_NO_EMPTY);
                                sort($guessed);
                                $hangman->guessed = implode($guessed);
                                $hangman->save();
                                $win = $this->assessWin($hangman->guessed, $hangman->title);
                                }
                                else {
                                $message .= 'Invalid guess. Please enter a single letter that hasnt already been guessed.';
                                }
                            }
                        }
	// Uncomment the following methods and override them if needed
	/*
	public function filters()
	{
		// return the filter configuration for this controller, e.g.:
		return array(
			'inlineFilterName',
			array(
				'class'=>'path.to.FilterClass',
				'propertyName'=>'propertyValue',
			),
		);
	}

	public function actions()
	{
		// return external action classes, e.g.:
		return array(
			'action1'=>'path.to.ActionClass',
			'action2'=>array(
				'class'=>'path.to.AnotherActionClass',
				'propertyName'=>'propertyValue',
			),
		);
	}
	*/
                     
}